﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
using System.ComponentModel;
using fap_PLC;
using System.Xml;
using HslCommunication.Core;

namespace fap
{

    public class 运动控制数据
    {


        public static Siemens_Interface 西门子PLC = new Siemens_Interface();
        public static string 主路径 = System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
        //public static string 主路径 = @"D:\\外观测试机";
        public static string 参数路径 = 主路径 + "\\Setting\\Prouduct\\";
        public static string Product路径 = "";
        public static string Product名字 = "";


        public static List<string> 输入地址 = new List<string> { "DB1.10000", "DB1.10001", "DB1.10002" };
        public static List<string> 输出地址 = new List<string> { "DB1.10003", "DB1.10004" };
        public static List<string> 报警地址 = new List<string> { "DB1.10006", "DB1.10007", "DB1.10008", "DB1.100010", "DB1.10011", "DB1.10012" };
        public static List<string> M地址 = new List<string> { "DB1.10022", "DB1.10023", "DB1.10078" };
        public static List<string> 屏蔽地址 = new List<string> { "DB1.10078" };
        public static List<string> 手动地址 = new List<string> { "DB1.10021" };
        public static List<string> 读取参数地址 = new List<string> { "DB1.10014", "DB1.10016", "DB1.10080", };
        public static List<string> 写入参数地址 = new List<string> { "DB1.10024", "DB1.10026", "DB1.10030", "DB1.10032", "DB1.10034", "DB1.10036", "DB1.10038", "DB1.10040", "DB1.10042", "DB1.10044" };

        //public static List<string>  状态地址= new List<string> { "DB1.10046" };

        public static string 心跳地址 = "DB1.10020";
        public static string 状态地址 = "DB1.10046";
        //public static string 手动地址 = "DB1.10021";
        public static 类.结果类[] M读取结果 = new 类.结果类[Enum.GetNames(typeof(枚举.M枚举)).Count()];
        public static 类.结果类[] I读取结果 = new 类.结果类[Enum.GetNames(typeof(枚举.I枚举)).Count()];
        public static 类.结果类[] Q读取结果 = new 类.结果类[Enum.GetNames(typeof(枚举.Q枚举)).Count()];
        public static 类.结果类[] 报警读取结果 = new 类.结果类[Enum.GetNames(typeof(枚举.报警枚举)).Count()];
        public static 类.结果类[] 屏蔽写入结果 = new 类.结果类[Enum.GetNames(typeof(枚举.屏蔽枚举)).Count()];
        public static 类.结果类[] 参数读取结果 = new 类.结果类[Enum.GetNames(typeof(枚举.读取参数枚举)).Count()];
        public static 类.结果类[] 参数写入数值 = new 类.结果类[Enum.GetNames(typeof(枚举.写入参数枚举)).Count()];

        public static short 状态结果 = 0;
        public static 枚举.M枚举 修改M点位;
        public static 枚举.SD枚举 修改SD点位;
        public static 枚举.Q枚举 修改Q点位;
        public static bool M写入 = false;
        public static bool M写入值 = false;
        public static bool SD写入 = false;
        public static bool SD归零 = false;
        public static bool Q写入 = false;
        public static bool 屏蔽写入 = false;
        public static bool 参数写入 = false;
        public static Thread 读取线程;


        static public void 初始化()
        {
            for (int x = 0; x < M读取结果.Count(); x++) { M读取结果[x] = new 类.结果类(); }
            for (int x = 0; x < I读取结果.Count(); x++) { I读取结果[x] = new 类.结果类(); }
            for (int x = 0; x < Q读取结果.Count(); x++) { Q读取结果[x] = new 类.结果类(); }
            for (int x = 0; x < 报警读取结果.Count(); x++) { 报警读取结果[x] = new 类.结果类(); }
            for (int x = 0; x < 屏蔽写入结果.Count(); x++) { 屏蔽写入结果[x] = new 类.结果类(); }
            for (int x = 0; x < 参数读取结果.Count(); x++) { 参数读取结果[x] = new 类.结果类(); }
            for (int x = 0; x < 参数写入数值.Count(); x++) { 参数写入数值[x] = new 类.结果类(); }

        }
        public static bool 连接PLC()
        {
            西门子PLC.Init_通用(HslCommunication.Profinet.Siemens.SiemensPLCS.S200Smart);
            西门子PLC.IP = "192.168.1.41";
            string str = 西门子PLC.Connect();
            if (str == "True")
            {
                读取线程 = new Thread(读取线程方法);
                读取线程.Start();
                return true;
            }
            else
            {
                return false;

            }
        }


        static public void 读取线程方法()
        {



            int 心跳 = 0;
            while (true)
            {
                Thread.Sleep(100);

                if (西门子PLC.状态)
                {
                    ///心跳
                    ///
                    if (心跳 == 1)
                    {
                        心跳 = 0;
                    }
                    else
                    {
                        心跳 = 1;
                    }
                    西门子PLC.Write_value<byte>(心跳地址, (byte)心跳);
                    西门子PLC.Read_value<short>(状态地址, out 状态结果);

                    for (int x = 0; x < M地址.Count(); x++)
                    {
                        西门子PLC.Read_value<byte>(M地址[x], out byte M结果);

                        for (int i = 0; i < 8; i++)
                        {
                            if ((M结果 >> i) % 2 == 1)
                            {
                                M读取结果[i + x * 8].结果 = true;
                            }
                            else
                            {
                                M读取结果[i + x * 8].结果 = false;
                            }
                        }
                    }

                    for (int x = 0; x < 输入地址.Count(); x++)
                    {
                        西门子PLC.Read_value<byte>(输入地址[x], out byte i结果);

                        for (int i = 0; i < 8; i++)
                        {
                            if ((i结果 >> i) % 2 == 1)
                            {
                                I读取结果[i + x * 8].结果 = true;
                            }
                            else
                            {
                                I读取结果[i + x * 8].结果 = false;
                            }
                        }
                    }
                    for (int x = 0; x < 输出地址.Count(); x++)
                    {
                        西门子PLC.Read_value<byte>(输出地址[x], out byte Q结果);

                        for (int i = 0; i < 8; i++)
                        {
                            if ((Q结果 >> i) % 2 == 1)
                            {
                                Q读取结果[i + x * 8].结果 = true;
                            }
                            else
                            {
                                Q读取结果[i + x * 8].结果 = false;
                            }
                        }
                    }

                    for (int x = 0; x < 报警地址.Count(); x++)
                    {
                        西门子PLC.Read_value<byte>(报警地址[x], out byte 报警结果);

                        for (int i = 0; i < 8; i++)
                        {
                            if ((报警结果 >> i) % 2 == 1)
                            {
                                报警读取结果[i + x * 8].结果 = true;
                            }
                            else
                            {
                                报警读取结果[i + x * 8].结果 = false;
                            }
                        }
                    }
                    //for (int x = 0; x < 屏蔽地址.Count(); x++)
                    //{
                    //    西门子PLC.Read_value<byte>(屏蔽地址[x], out byte 屏蔽结果);

                    //    for (int i = 0; i < 8; i++)
                    //    {
                    //        if ((屏蔽结果 >> i) % 2 == 1)
                    //        {
                    //            屏蔽读取结果[i + x * 8].结果 = true;
                    //        }
                    //        else
                    //        {
                    //            屏蔽读取结果[i + x * 8].结果 = false;
                    //        }
                    //    }
                    //}
                    for (int x = 0; x < 读取参数地址.Count(); x++)
                    {
                        if (x == (int)枚举.读取参数枚举.产量计数)
                        {
                            西门子PLC.Read_value<int>(读取参数地址[x], out int 参数结果);
                            参数读取结果[x].数值 = (int)参数结果;
                        }
                        else
                        {
                            西门子PLC.Read_value<short>(读取参数地址[x], out short 参数结果);
                            参数读取结果[x].数值 = (int)参数结果;
                        }


                    }

                  
                    if (M写入)
                    {
                       
                        M写入 = false;
                        string str = "";
                        for (int x = 0; x < M读取结果.Count(); x++)
                        {
                            if ((int)修改M点位 == x)
                            {
                                M读取结果[x].结果 = M写入值;
                            }
                            if (M读取结果[x].结果)
                            {
                                str = "1" + str;
                            }
                            else
                            {
                                str = "0" + str;
                            }
                        }
                        //short bytes = Convert.ToInt16(str, 2);
                        byte[] bytes = BinaryStringToByteArray(str);
                        for (int x = 0; x < bytes.Length; x++)
                        {
                            西门子PLC.Write_value<byte>(M地址[x], bytes[x]);
                        }
                        Thread.Sleep(500);
                    }

                    if (SD写入)
                    {
                        SD写入 = false;
                        西门子PLC.Read_value<byte>(手动地址[0], out byte SD结果);


                        bool[] 结果 = new bool[8];

                        for (int i = 0; i < 结果.Count(); i++)
                        {
                            if ((SD结果 >> i) % 2 == 1)
                            {
                                结果[i] = true;
                            }
                            else
                            {
                                结果[i] = false;

                            }
                        }
                        string str = "";
                        for (int x = 0; x < 结果.Count(); x++)
                        {
                            if ((int)修改SD点位 == x)
                            {
                                结果[x] = !结果[x];
                            }
                            if (结果[x])
                            {
                                str = "1" + str;
                            }
                            else
                            {
                                str = "0" + str;

                            }
                        }
                        byte bytes = Convert.ToByte(str, 2);

                        西门子PLC.Write_value<byte>(手动地址[0], bytes);
                        Thread.Sleep(200);

                        //西门子PLC.Write_value<byte>(手动地址[0], 0);
                        //Thread.Sleep(100);

                    }

                    if (SD归零)
                    {
                        SD归零 = false;
                     
                        西门子PLC.Write_value<byte>(手动地址[0], 0);
                        Thread.Sleep(100);

                    }

                    if (Q写入)
                    {
                        Q写入 = false;

                        string str = "";
                        for (int x = 0; x < Q读取结果.Count(); x++)
                        {
                            if ((int)修改Q点位 == x)
                            {
                                Q读取结果[x].结果 = !Q读取结果[x].结果;
                            }
                            if (Q读取结果[x].结果)
                            {
                                str = "1" + str;
                            }
                            else
                            {
                                str = "0" + str;

                            }
                        }
                        //short bytes = Convert.ToInt16(str, 2);
                        byte[] bytes = BinaryStringToByteArray(str);

                        for (int x = 0; x < bytes.Length; x++)
                        {
                            西门子PLC.Write_value<byte>(输出地址[x], bytes[x]);

                        }
                        Thread.Sleep(100);

                    }
                    if (屏蔽写入)
                    {
                        屏蔽写入 = false;

                        string str = "";
                        for (int x = 0; x < 屏蔽写入结果.Count(); x++)
                        {

                            if (屏蔽写入结果[x].结果)
                            {
                                str = "1" + str;
                            }
                            else
                            {
                                str = "0" + str;
                            }
                        }
                        //short bytes = Convert.ToInt16(str, 2);
                        byte[] bytes = BinaryStringToByteArray(str);

                        for (int x = 0; x < bytes.Length; x++)
                        {
                            西门子PLC.Write_value<byte>(屏蔽地址[x], bytes[x]);

                        }
                        Thread.Sleep(100);

                    }
                    if (参数写入)
                    {
                        参数写入 = false;

                        string str = "";
                        for (int x = 0; x < 参数写入数值.Count(); x++)
                        {
                            if (x == (int)枚举.写入参数枚举.底板放入个数)
                            {
                                西门子PLC.Write_value<int>(写入参数地址[x], (int)参数写入数值[x].数值);

                            }
                            else
                            {
                                西门子PLC.Write_value<short>(写入参数地址[x], (short)参数写入数值[x].数值);
                            }

                        }
                        Thread.Sleep(100);
                    }
                }
            }

        }
        public static void 保存()
        {
            try
            {
                if (Product路径 != null)
                {
                    string path = Product路径 + "\\参数.ini";
                    string 主path = 主路径 + "\\主参数.ini";
                 

                    for (int x = 0; x < 屏蔽写入结果.Count(); x++)
                    {
                        IniFile.Write_Value(path, "屏蔽", "屏蔽" + x.ToString(), 屏蔽写入结果[x].结果.ToString());
                    }
                    屏蔽写入 = true;

                    for (int x = 0; x < 参数写入数值.Count(); x++)
                    {
                        IniFile.Write_Value(path, "参数", "参数"+ x.ToString(), 参数写入数值[x].数值.ToString());
                    }
                    参数写入 = true;
                    窗口.主页主显示.显示("保存配方:" + 运动控制数据.Product名字);
                    IniFile.Write_Value(path, "主控", "当前选择配方", 窗口.主页主显示.配方选择.SelectedIndex.ToString());

                    
                }
            }
            catch { return; }

        }

        public static void 读取()
        {
            try
            {
                if (Product路径 != null)
                {
                    string path = Product路径 + "\\参数.ini";
                 

                    for (int x = 0; x < 屏蔽写入结果.Count(); x++)
                    {



                        string st = IniFile.Read_Value(path, "屏蔽", "屏蔽" + x.ToString(), "False");
                        屏蔽写入结果[x].结果 = Convert.ToBoolean(st);
                    }
                    屏蔽写入 = true;
                    for (int x = 0; x < 参数写入数值.Count(); x++)
                    {
                        string st = IniFile.Read_Value(path, "参数", "参数" + x.ToString(), "0");
                        参数写入数值[x].数值 = Convert.ToDouble(st);
                    }
                    参数写入 = true;
                    窗口.主页主显示.显示("读取配方:" + 运动控制数据.Product名字);
                }
            }
            catch { return; }



        }

        public static void 停止()
        {

        }

        // 将二进制字符串转换为字节数组
        public static byte[] BinaryStringToByteArray(string binaryString)
        {


            // 计算字节数组的长度（每8个二进制位对应一个字节）
            int numOfBytes = binaryString.Length / 8;

            // 创建字节数组
            byte[] byteArray = new byte[numOfBytes];

            // 遍历二进制字符串的每8个字符，将其转换为一个字节并存储在字节数组中
            for (int i = 0; i < numOfBytes; i++)
            {


                // 从二进制字符串中提取8个字符作为一个字节的二进制表示
                string byteString = binaryString.Substring(i * 8, 8);

                // 将字节的二进制表示转换为一个字节，并存储在字节数组中
                byteArray[i] = Convert.ToByte(byteString, 2);
            }

            // 返回字节数组
            return byteArray;
        }

    }



    public class 主数据
    {
        static public 枚举.权限 当前权限 = 枚举.权限.操作员;

        static public bool 开始 = false, 停止 = true, 暂停 = false, 复位 = true;

        static public int 页面选择 = -1;

    }

    public class 窗口
    {
        //static public 主界面 主界面;
        static public 主页 主页;
        static public 主页主显示 主页主显示;
        static public 运动控制 运动控制;
        static public 运动控制首页 运动控制首页;
        static public 运动控制感应器屏蔽页 运动控制感应器屏蔽页;
        static public 主页辅显示 主页辅显示;





        static public 统计 统计;

        static public void 窗口初始化()
        {
            运动控制数据.初始化();
            //主界面 = new 主界面();
            主页 = new 主页();
            主页主显示 = new 主页主显示();
            主页辅显示 = new 主页辅显示();
            运动控制 = new 运动控制();
            统计 = new 统计();
            运动控制首页 = new 运动控制首页();
            运动控制感应器屏蔽页 = new 运动控制感应器屏蔽页();
        }


    }

    public class 枚举
    {
        #region 权限
        public enum 权限 { 工程师, 管理员, 操作员 };
        public enum SD枚举 { 推动1正 = 0, 推动2正, 推动3正, 推动4正, 推动1反 , 推动2反, 推动3反, 推动4反, }
        public enum 屏蔽枚举 { 推动1到位 = 0, 推动1原位, 推动2到位, 推动2原位, 推动3到位, 推动3原位, 推动4到位, 推动4原位, }

        #endregion
        public enum M枚举 { 备用, 开始计数 = 1, 产量清零, 手自动, 复位, 运行, 停止, 暂停, 备用0, 备用1, 备用2, 备用3, 蜂鸣器屏蔽, 保存, 读取, 备用7, 推动1到位, 推动1原位, 推动2到位, 推动2原位, 推动3到位, 推动3原位, 推动4到位, 推动4原位 }
        public enum I枚举 { I_急停 = 0, I_停止, I_启动, I_复位, I_计数启动, I_计数停止, I_面板急停, I_0_7, I_工装检测1, I_工装检测2, I_工装检测3, I_工装检测4, I_1_4, I_1_5, I_1_6, I_1_7, I_推动气缸1原位, I_推动气缸1进位, I_推动气缸2原位, I_推动气缸2进位, I_推动气缸3原位, I_推动气缸3进位, I_推动气缸4原位, I_推动气缸4进位, }
        public enum Q枚举 { Q_红灯 = 0, Q_绿灯, Q_黄灯, Q_蜂鸣器, Q_电脑开机, Q_0_5, Q_0_6, Q_0_7, Q_推动气缸1, Q_推动气缸2, Q_推动气缸3, Q_推动气缸4, Q_1_4, Q_1_5, Q_1_6, Q_1_7, }
        public enum 报警枚举 { 急停被按下 = 0, 预留1, 预留2, 预留3, 预留4, 与上位机未建立通讯连, 面板急停被按下, 预留5, 设备停止被按下, 备用1, 备用2, 备用3, 备用4, 备用5, 备用6, 备用7, 推动气缸1原位异常, 推动气缸2原位异常, 推动气缸3原位异常, 推动气缸4原位异常, 备用8, 备用9, 备用10, 备用11, 推动气缸1原位报警, 推动气缸1到位报警, 推动气缸1故障报警, 推动气缸2原位报警, 推动气缸2到位报警, 物料检测1异常, 推动气缸2故障报警, 备用12, 推动气缸3原位报警, 推动气缸3到位报警, 推动气缸3故障报警, 推动气缸4原位报警, 推动气缸4到位报警, 物料检测2异常, 推动气缸4故障报警, 备用13, 物料检测3异常, 物料检测4异常, 设备暂停中, 备用14, 备用15, 备用16, 备用17, 备用18, }
        public enum 读取参数枚举 { 生产节拍 = 0, 产量计数, 配方编号 }
        public enum 写入参数枚举 { 运动节拍, 底板放入个数, SZ_推动1原位延, SZ_推动1到位延, SZ_推动2原位延, SZ_推动2到位延, SZ_推动3原位延, SZ_推动3到位延, SZ_推动4原位延, SZ_推动4到位延, }

    }


    public class 类
    {
        public class 结果类 : INotifyPropertyChanged
        {

            bool _结果 = false;
            public bool 结果
            {
                get { return this._结果; }
                set
                {
                    this._结果 = value;

                    OnPropertyChanged("结果");
                    OnPropertyChanged("图像");

                }
            }

            double _数值 = 0;

            public double 数值
            {
                get { return this._数值; }
                set
                {
                    this._数值 = value;

                    OnPropertyChanged("数值");
                    OnPropertyChanged("显示数值");

                }
            }

            public double 显示数值
            {
                get { return this._数值/10; }
                set
                {
                    this._数值 =(value*10.0);

                    OnPropertyChanged("数值");
                    OnPropertyChanged("显示数值");

                }
            }

            public System.Windows.Media.Imaging.BitmapImage 图像
            {
                get 
                { 
                    if(结果)
                    {
                        return 绿灯;
                    }
                    else
                    {
                        return 红灯;

                    }
                    }

               
            }
            System.Windows.Media.Imaging.BitmapImage 绿灯= new System.Windows.Media.Imaging.BitmapImage(new Uri("/fap;component/素材/运动控制页面/绿灯.png", UriKind.Relative));
            System.Windows.Media.Imaging.BitmapImage 红灯= new System.Windows.Media.Imaging.BitmapImage(new Uri("/fap;component/素材/运动控制页面/红灯.png", UriKind.Relative));

            public event PropertyChangedEventHandler PropertyChanged;

            void OnPropertyChanged(string name)
            {
                if (PropertyChanged != null)
                    this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }


    }










}
